package com.joysuch.wwyt.bp.websocket;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Sets;
import com.joysuch.wwyt.bp.entity.risk.BpCompany;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;

//@ServerEndpoint(value = "/bp/risk/bigScreen/{orgCode}")
//@Component
@Slf4j
public class WebSocket {

    private static int onlineCount = 0;
    //private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>();
    //所有连接 key:orgCode
    private static Map<String, CopyOnWriteArraySet<WebSocket>> webSocketMap = new ConcurrentHashMap<>();
    private Session session;

    //private volatile static BpCompany bpCompany;

    //key:orgCode  value:bpCompany
    private static Map<String, BpCompany> bigScreenMap = new ConcurrentHashMap<>();

    public void removeWebSocket(String orgCode) {
        CopyOnWriteArraySet<WebSocket> webSockets = webSocketMap.get(orgCode);
        webSockets.remove(this);
    }

//    public static void putBpCompany(BpCompany bc) {
//
//    }

//    public static void setBpCompany(BpCompany bc) {
//        bpCompany = bc;
//    }
//
//    public static BpCompany getBpCompany() {
//        return bpCompany;
//    }

    //10点更新，当天没有公告需要清除数据
    public static void resetWebsocketContent(List<BpCompany> list) {
        Set<BpCompany> allSet = bigScreenMap.values().stream().collect(Collectors.toSet());
        Set<BpCompany> collect = list.stream().collect(Collectors.toSet());
        Sets.SetView<BpCompany> difference = Sets.difference(allSet, collect);
        for (BpCompany bpCompany : difference) {
            String orgCode = bpCompany.getOrgCode();
            log.info("orgCode:" + orgCode + "，当天无大屏数据，执行清除操作");
            BpCompany bpCompany1 = new BpCompany();
            bpCompany1.setOrgCode(orgCode);
            putBigScreenMap(bpCompany1);
            sendInfo(bpCompany1);
        }
    }

    public static void putBigScreenMap(BpCompany bc) {
        String orgCode = convertOrgCode(bc.getOrgCode());
        if (orgCode != null) {
            bigScreenMap.put(orgCode, bc);
        }
    }

    public static BpCompany getBigScreenMap(String orgCode) {
        orgCode = convertOrgCode(orgCode);
        return bigScreenMap.get(orgCode);
    }

    public static Map getScreenMap() {
        return bigScreenMap;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam(value = "orgCode") String orgCode, Session session) {
        this.session = session;
        //webSocketSet.add(this);
        if (StringUtils.isNotEmpty(orgCode)) {
            orgCode = convertOrgCode(orgCode);
            CopyOnWriteArraySet<WebSocket> webSockets = webSocketMap.get(orgCode);
            if (webSockets == null) {
                webSockets = new CopyOnWriteArraySet<>();
            }
            webSockets.add(this);
            webSocketMap.put(orgCode, webSockets);
            session.getUserProperties().put("orgCode", orgCode);
        }
        log.info("一个连接进来。。。");
        addOnlineCount();

        //一连接即推消息
        BpCompany bpCompany = bigScreenMap.get(orgCode);
        if (bpCompany != null) {
            try {
                session.getBasicRemote().sendText(JSON.toJSONString(bpCompany));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static String convertOrgCode(String orgCode) {
        if (orgCode != null && orgCode.length() > 7) {
            orgCode = orgCode.substring(0, 7);
        }
        return orgCode;
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        String orgCode = (String) session.getUserProperties().get("orgCode");
        removeWebSocket(orgCode);
//        webSocketSet.remove(this);
        subOnlineCount();
        log.info("离线。。。");
    }

    /**
     * * 收到客户端消息后调用的方法
     * *
     * * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        if ("ping".equals(message)) {
            try {
                if (session != null && session.isOpen()) {
                    session.getBasicRemote().sendText("pong");
                }
            } catch (IOException e) {
                log.error("websocket返回心跳消息出错：" + e.getMessage());
            }
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("websocket连接出错：" + error.getMessage());
    }


    public void sendMessage(String message) throws IOException {
        if (session != null && session.isOpen()) {
            session.getBasicRemote().sendText(message);
        }
    }

    /**
     * 群发自定义消息
     */
    public static void sendInfo(BpCompany bpCompany) {
        String orgCode = convertOrgCode(bpCompany.getOrgCode());
        if (orgCode == null) {
            return;
        }
        CopyOnWriteArraySet<WebSocket> webSocketSet = webSocketMap.get(orgCode);
        if (webSocketSet == null) {
            return;
        }
        for (WebSocket item : webSocketSet) {
            try {
                item.sendMessage(JSON.toJSONString(bpCompany));
            } catch (IOException e) {
                log.error("websocket群发消息出错：" + e.getMessage());
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocket.onlineCount--;
    }
}

